import {SelectionModel, TextModel} from "../models";
import {EventEmitter} from "events";
import {debounce} from "../utils/debounce";

export class SourceView extends EventEmitter {
    private textModel_: TextModel;
    private selectionModel_: SelectionModel;
    private viewContainer_: HTMLElement;

    constructor(textModel: TextModel, selectionModel: SelectionModel, viewContainer: HTMLElement) {
        super()
        this.textModel_ = textModel
        this.selectionModel_ = selectionModel
        this.viewContainer_ = viewContainer
        this.addEventListener()
    }

    //监听数据模型变化，并且更新视图
    private addEventListener() {
        this.textModel_.on('text-change', this.render.bind(this))
        const domSelectionChangeHandlerBinder_ = debounce(this.domSelectionChangeHandler.bind(this), 50)
        window.document.addEventListener('selectionchange', domSelectionChangeHandlerBinder_)
    }

    domSelectionChangeHandler() {
        const domSelection = window.getSelection()
        if (domSelection) {
            this.emit('selection-change', {anchor: domSelection.anchorOffset, focus: domSelection.focusOffset})
        }
    }

    private updateDomSelection() {
        const domSelection = window.getSelection()
        if (domSelection) {
            const selectionFromModel = this.selectionModel_.getSelection()
            const anchor = selectionFromModel.anchor
            const range = window.document.createRange()
            range.setStart(this.viewContainer_.childNodes[0], anchor)
            range.setEnd(this.viewContainer_.childNodes[0], anchor)
            domSelection.removeAllRanges()
            domSelection.addRange(range)
        }
    }

    render() {
        this.viewContainer_.innerHTML = this.textModel_.getSpacers()
        setTimeout(() => {
            this.updateDomSelection()
        })
    }
}